import {FrameBuffer} from "../output/FrameBuffer";
import {Vector4} from "../math/Vector4";
import {IVector2} from "../math/types";

export class DrawLineUtil {

    static drawLine_1(p0: IVector2, p1: IVector2, color: Vector4, frame: FrameBuffer) {
        const dx = p1.x - p0.x;
        const dy = p1.y  - p0.y;
        const k = dy / dx;
        for (let x = p0.x, y=p0.y; x <= p1.x; x++) {
            frame.drawPoint(x, Math.round(y), color);
            y += k;
        }
    }

    static drawLine_2(p0: IVector2, p1: IVector2, color: Vector4, frame: FrameBuffer) {
        const dx = p1.x - p0.x;
        const dy = p1.y  - p0.y;
        if (Math.abs(dx) > Math.abs(dy)) {
            // 以 x 轴 进行步长
            const d = dy/dx;
            if (p1.x > p0.x) {
                for (let {x, y} = p0; x <= p1.x; x++) {
                    frame.drawPoint(x, Math.round(y), color);
                    y += d;
                }
            } else {
                for (let {x, y} = p0; x >= p1.x; x--) {
                    frame.drawPoint(x, Math.round(y), color);
                    y += d;
                }
            }
        } else {
            // 以 y 轴 进行步长
            const d = dx/dy;
            if (p1.y > p0.y) {
                for (let {x, y} = p0; y <= p1.y; y++) {
                    frame.drawPoint(Math.round(x), y, color);
                    x += d;
                }
            } else {
                for (let {x, y} = p0; y >= p1.y; y--) {
                    frame.drawPoint(Math.round(x), y, color);
                    x += d;
                }
            }
        }
    }

    static drawLine_3(p0: IVector2, p1: IVector2, color: Vector4, frame: FrameBuffer) {
        const dx = p1.x - p0.x;
        const dy = p1.y  - p0.y;
        const k = dy/dx;
        let e = -0.5;
        for (let {x, y}  = p0; x < p1.x; x++) {
            frame.drawPoint(x, y, color);
            e += k;
            if (e > 0) {
                e -= 0.5;
                y++;
            }
        }
    }
    static drawLine_4(p0: IVector2, p1: IVector2, color: Vector4, frame: FrameBuffer) {
        const dx = p1.x - p0.x;
        const dy = p1.y  - p0.y;
        const k = dy/dx;
        // 整形加速
        let e = -dx;
        for (let {x, y}  = p0; x < p1.x; x++) {
            frame.drawPoint(x, y, color);
            e += 2 * dy;
            if (e > 0) {
                e -= 2 * dx;
                y++;
            }
        }
    }

    static drawLine_5(p0: IVector2, p1: IVector2, color: Vector4, frame: FrameBuffer) {
        let x0 = p0.x, y0 = p0.y, x1 = p1.x, y1 = p1.y, temp = 0, swap = false;
        if (Math.abs(x0  - x1) < Math.abs(y0 - y1)) {
            // 交换轴
            temp = x0; x0 = y0; y0 = temp;
            temp = x1; x1 = y1; y1 = temp;
            swap = true;
        }
        if (x0 > x1) {
            // 交换点
            temp = x0; x0 = x1; x1 = temp;
            temp = y0; y0 = y1; y1 = temp;
        }

        const dx = Math.abs(x0 - x1);
        const dy = Math.abs(y0 - y1);
        const yStep = y1 > y0 ? 1 : -1;
        let e = -dx;
        for (let x = x0, y = y0; x < x1; x++)  {
            if (swap) {
                frame.drawPoint(y, x, color);
            } else {
                frame.drawPoint(x, y, color);
            }
            e += 2* dy;
            if (e > 0) {
                y += yStep;
                e -= 2*dx;
            }
        }
    }

    static drawLine = DrawLineUtil.drawLine_5;

}